package com.xbongbong.saas.service.impl;


import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.distributor.dto.DistributorAreaAddDTO;
import com.xbongbong.distributor.dto.DistributorAreaDelDTO;
import com.xbongbong.distributor.dto.DistributorAreaListDTO;
import com.xbongbong.distributor.dto.DistributorAreaSortDTO;
import com.xbongbong.distributor.dto.DistributorAreaUpdateDTO;
import com.xbongbong.distributor.vo.DistributorAreaAddVO;
import com.xbongbong.distributor.vo.DistributorAreaDelVO;
import com.xbongbong.distributor.vo.DistributorAreaListVO;
import com.xbongbong.distributor.vo.DistributorAreaSortVO;
import com.xbongbong.distributor.vo.DistributorAreaUpdateVO;
import com.xbongbong.distributor.vo.DistributorAreaVO;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.elasticsearch.model.PaasEsModel;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.model.PaasFormModel;
import com.xbongbong.paas.pojo.vo.DepartmentSimpleListVO;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.DateUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.pro.enums.DistributorMarkEnum;
import com.xbongbong.pro.enums.ErrorCodeEnum;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.DistributorErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.DistributorAreaEntity;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.DistributorEnum;
import com.xbongbong.saas.model.DistributorAreaModel;
import com.xbongbong.saas.model.IndexTypeModel;
import com.xbongbong.saas.service.DistributorAreaService;
import org.apache.commons.collections4.CollectionUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;


/**
 *
 * @author mengna.deng
 * @date 2020/12/23 17:59
 * @version 1.0
 * @since V1.0
 */
@Service("distributorAreaService")
public class DistributorAreaServiceImpl implements DistributorAreaService {

    private static final Logger LOG = LoggerFactory.getLogger(DistributorAreaServiceImpl.class);

    @Resource
    private DistributorAreaModel distributorAreaModel;
    @Resource
    private PaasEsModel paasEsModel;
    @Resource
    private PaasFormModel paasFormModel;
    @Resource
    private IndexTypeModel indexTypeModel;


    @Override
    public DistributorAreaListVO list(DistributorAreaListDTO distributorAreaListDTO) throws XbbException {
        DistributorAreaListVO distributorAreaListVO = new DistributorAreaListVO();
        try{
            Map<String, Object> param = BeanUtil.convertBean2Map(distributorAreaListDTO, true);
            param.put("orderByStr", "sort ASC, update_time ASC ");
            List<DistributorAreaEntity> distributorAreaList = distributorAreaModel.findEntities(param);

            if (Objects.isNull(distributorAreaList)) {
                distributorAreaListVO.setDistributorAreaList(new ArrayList<>());
                return distributorAreaListVO;
            }

            List<DistributorAreaVO> distributorAreaVOS = new ArrayList<>();
            for(DistributorAreaEntity distributorAreaEntity: distributorAreaList) {
                if (StringUtil.isNotEmpty(distributorAreaListDTO.getNameLike())) {
                    distributorAreaVOS.add(new DistributorAreaVO(){{
                        BeanUtil.copyProperties(distributorAreaEntity, this);
                    }});
                } else {
                    if (distributorAreaEntity.getParentId().equals(0L)){
                        distributorAreaVOS.add(new DistributorAreaVO(){{
                            BeanUtil.copyProperties(distributorAreaEntity, this);
                            setChildList(new ArrayList<DistributorAreaVO>(){{
                                if (Objects.nonNull(getChildDistributorAreaTree(distributorAreaList, distributorAreaEntity.getId()))){
                                    addAll(getChildDistributorAreaTree(distributorAreaList, distributorAreaEntity.getId()));
                                }
                            }});
                        }});
                    }
                }
            }
            distributorAreaListVO.setDistributorAreaList(distributorAreaVOS);
        }catch (Exception e){
            LOG.error("distributorAreaServiceImpl.list 执行出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return distributorAreaListVO;
    }

    /**
     * 获取子节点数
     * @param distributorAreaList
     * @param parentId
     * @return
     */
    private List<DistributorAreaVO> getChildDistributorAreaTree(List<DistributorAreaEntity> distributorAreaList, Long parentId) {
        List<DistributorAreaVO> distributorAreaVOS = new ArrayList<>();
        List<DistributorAreaVO> distributorAreaVOList = getChildDistributorAreaList(distributorAreaList, parentId);
        if (distributorAreaVOList.isEmpty()) {
            return null;
        }
        for (DistributorAreaVO item : distributorAreaVOList) {
            List<DistributorAreaVO> childProductCategoryList = getChildDistributorAreaTree(distributorAreaList, item.getId());
            item.setChildList(childProductCategoryList);
            distributorAreaVOS.add(item);
        }
        return distributorAreaVOS;
    }

    /**
     * 获取子节点列表
     * @param distributorAreaList
     * @param parentId
     * @return
     */
    private List<DistributorAreaVO> getChildDistributorAreaList(List<DistributorAreaEntity> distributorAreaList, Long parentId) {
        List<DistributorAreaVO> distributorAreaVOS = new ArrayList<>();
        for (DistributorAreaEntity distributorAreaEntity: distributorAreaList) {
            if (distributorAreaEntity.getParentId().equals(parentId)) {
                DistributorAreaVO productCategoryVO = new DistributorAreaVO();
                BeanUtil.copyProperties(distributorAreaEntity, productCategoryVO);
                distributorAreaVOS.add(productCategoryVO);
            }
        }
        return distributorAreaVOS;
    }


    @Override
    public DistributorAreaAddVO add(DistributorAreaAddDTO distributorAreaAddDTO) throws XbbException {
        try{
            String corpid = distributorAreaAddDTO.getCorpid();
            DistributorAreaEntity parentEntity;

            Long parentId = 0L;
            if (!Objects.isNull(distributorAreaAddDTO.getParentId())){
                parentId = distributorAreaAddDTO.getParentId();
            }

            //同级重名校验开始
            Long finalParentId = parentId;
            Map<String,Object> param = new HashMap<String,Object>(PaasConstant.DEFAULT_INITIAL_CAPACITY){{
                put("name",distributorAreaAddDTO.getName());
                put("parentId", finalParentId);
                put("del",0);
                put("corpid",corpid);
            }};
            List<DistributorAreaEntity> areaEntities = distributorAreaModel.findEntities(param);
            if (!Objects.isNull(areaEntities) && areaEntities.size()>0){
                //同级重名抛出异常
                throw new XbbException(DistributorErrorCodeEnum.API_ERROR_251001);
            }
            //同级重名校验结束

            Integer count = 0;
            //最多8级校验开始
            if (!Objects.equals(parentId,0L)){
                parentEntity = distributorAreaModel.getByKey(parentId,corpid);
                String router = parentEntity.getRouter();
                if (!Objects.isNull(router)){
                    String[] ids = router.split("\\|");
                    count = 0;
                    for (String id:ids) {
                        if (!id.isEmpty() && !Objects.equals(id,"\\|")){
                            count++;
                            if (count >= 8){
                                //层级已经到达了8级，不能再添加了
                                throw new XbbException(DistributorErrorCodeEnum.API_ERROR_251002);
                            }
                        }
                    }
                }
            }
            //最多8级校验结束


            //单层50个校验，并获取sort开始
            param.clear();
            param.put("parentId",parentId);
            param.put("del",0);
            param.put("corpid",corpid);
            count = distributorAreaModel.getEntityCount(param);
            if (count >= 50 ){
                //层级超过50层抛出异常
                throw new XbbException(DistributorErrorCodeEnum.API_ERROR_251003);
            }
            //单层50个校验，并获取sort结束

            //insert数据
            int finalCount = count + 1;
            DistributorAreaEntity addEntity = new DistributorAreaEntity(){{
                BeanUtils.copyProperties(distributorAreaAddDTO,this);
                setSort(finalCount);
                setDel(0);
                setCreatorId(distributorAreaAddDTO.getUserId());
                Long now = DateTimeUtil.getInt();
                setAddTime(now);
                setUpdateTime(now);
            }};
            addEntity.setParentId(parentId);
            distributorAreaModel.insert(addEntity);

            //更新router
            addEntity.setUpdateTime(DateTimeUtil.getInt());
            if (Objects.equals(parentId,0L)){
                addEntity.setRouter("|"+addEntity.getId()+"|");
            }else {
                parentEntity = distributorAreaModel.getByKey(parentId,corpid);
                if (Objects.isNull(parentEntity)){
                    //parentId没有查出对象的entity，抛出异常
                    throw new XbbException(DistributorErrorCodeEnum.API_ERROR_251005);
                }
                addEntity.setRouter(parentEntity.getRouter() +addEntity.getId()+"|");
            }
            distributorAreaModel.update(addEntity);

        }catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("DistributorAreaServiceImpl.list 出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return new DistributorAreaAddVO();
    }

    @Override
    public DistributorAreaDelVO delete(DistributorAreaDelDTO distributorAreaDelDTO) throws XbbException {
        try{
            Long id = distributorAreaDelDTO.getId();
            String corpid = distributorAreaDelDTO.getCorpid();
            Map<String,Object> param = new HashMap<String,Object>(PaasConstant.DEFAULT_INITIAL_CAPACITY){{
                put("corpid",corpid);
                put("parentId", id);
                put("del", DelEnum.NORMAL.getDel());
            }};
            int distributorAreaCount = distributorAreaModel.getEntityCount(param);
            if (distributorAreaCount > 0) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.DISTRIBUTOR_AREA_NOT_ALLOW_DELETE);
            }
            DistributorAreaEntity distributorAreaEntity = distributorAreaModel.getByKey(id,corpid);
            if (Objects.isNull(distributorAreaEntity)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.DISTRIBUTOR_AREA_NOT_EXIST);
            }
            //如果该区域正在被经销商档案使用不允许删除
            BoolQueryBuilder boolQueryBuilder = boolQuery();
            List<Long> formIdList = paasFormModel.getFormIdList4Distributor(XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode(),corpid, DistributorMarkEnum.DISTRIBUTOR.getCode());
            if (CollectionUtils.isEmpty(formIdList)){
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.DISTRIBUTOR_FORM_NOT_EXIST);
            }
            //解析查询条件
            boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
            boolQueryBuilder.filter(termQuery("del",  DelEnum.NORMAL.getDel()));
            boolQueryBuilder.filter(termQuery("data." + DistributorEnum.AREA.getAttr()+ StringConstant.POINT + StringConstant.KEY_WORD, id));
            boolQueryBuilder.filter(termQuery("fromId", formIdList.get(0) ));
            IndexTypeEnum customerIndex = indexTypeModel.getCustomerIndex(corpid, XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode(), SaasMarkEnum.SAAS.getCode());
            Long count = paasEsModel.count(boolQueryBuilder, customerIndex);
            if (count>0){
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.DISTRIBUTOR_AREA_BEING_USED);
            }
            distributorAreaModel.delete(id,corpid);

        }catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("distributorAreaServiceImpl.del 出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return new DistributorAreaDelVO();

    }

    @Override
    public DistributorAreaUpdateVO update(DistributorAreaUpdateDTO distributorAreaUpdateDTO) throws XbbException {
        try {
            DistributorAreaEntity distributorAreaEntity = distributorAreaModel.getByKey(distributorAreaUpdateDTO.getId(),distributorAreaUpdateDTO.getCorpid());
            if (Objects.isNull(distributorAreaEntity)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001,MessageConstant.DISTRIBUTOR_AREA_NOT_EXIST_OR_DELETED);
            }
            distributorAreaModel.update(new DistributorAreaEntity(){{
                BeanUtils.copyProperties(distributorAreaUpdateDTO,this);
                setUpdateTime(DateTimeUtil.getInt());
            }});
        }catch (XbbException e) {
            throw e;
        }  catch (Exception e) {
            LOG.error("DistributorAreaServiceImpl.update 出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return new DistributorAreaUpdateVO();
    }

    @Override
    public DistributorAreaSortVO sort(DistributorAreaSortDTO distributorAreaSortDTO) throws XbbException {
        DistributorAreaSortVO productCategorySortVO = new DistributorAreaSortVO();
        try {
            String corpid = distributorAreaSortDTO.getCorpid();
            List<DistributorAreaVO> distributorAreaList = distributorAreaSortDTO.getDistributorAreaList();
            List<DistributorAreaEntity> updateDistributorAreaList = new ArrayList<>();
            getDistributorAreaList(updateDistributorAreaList, distributorAreaList, "");
            if (!updateDistributorAreaList.isEmpty()) {
                distributorAreaModel.updateBatch(updateDistributorAreaList, corpid);
            }
        } catch (Exception e) {
            LOG.error("DistributorAreaServiceImpl.sort 出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return productCategorySortVO;
    }

    @Override
    public DepartmentSimpleListVO areaFormList(DistributorAreaListDTO distributorAreaListDTO) throws XbbException {
        Map<String, Object> param = BeanUtil.convertBean2Map(distributorAreaListDTO, true);
        int count = distributorAreaModel.getEntityCount(param);
        List<DistributorAreaEntity> distributorAreaList = new ArrayList<>();
        param.put("orderByStr", "sort ASC, update_time ASC ");
        int start = 0;
        int pageNum = 2000;
        param.put("pageSize",pageNum);
        for (; start < count; start = start + pageNum) {
            // 分组数据的endIndex
            param.put("start",start);
            List<DistributorAreaEntity> subList = distributorAreaModel.findEntities(param);
            if (CollectionUtils.isNotEmpty(subList)){
                distributorAreaList.addAll(subList);
            }
        }
        DepartmentSimpleListVO departmentSimpleListVO = new DepartmentSimpleListVO();
        departmentSimpleListVO.setCorpid(distributorAreaListDTO.getCorpid());
        Map<Long, List<DistributorAreaEntity>> childMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        distributorAreaList.forEach(item -> {
            List<DistributorAreaEntity> childList = childMap.getOrDefault(item.getParentId(), new ArrayList<>());
            childList.add(item);
            childMap.putIfAbsent(item.getParentId(), childList);
        });
        List<DistributorAreaEntity> rootList = childMap.get(0L);
        JSONArray departmentTree = new JSONArray();
        if (rootList != null) {
            for (DistributorAreaEntity distributorAreaEntity : rootList) {
                JSONObject depJson = new JSONObject();
                depJson.put("value", distributorAreaEntity.getId());
                depJson.put("label", distributorAreaEntity.getName());
                depJson.put("type", "department");
                depJson.put("children", getSubDepartmentTree(childMap, distributorAreaEntity.getId()));
                departmentTree.add(depJson);
            }
        }
        departmentSimpleListVO.setDepartmentTree(departmentTree);
        return departmentSimpleListVO;
    }


    /**
     * 获取更新排序的数据
     * @param updateProductCategoryList
     * @param distributorAreaList
     * @param router
     * @return 返回更新排序的数据
     */
    private List<DistributorAreaEntity> getDistributorAreaList(List<DistributorAreaEntity> updateProductCategoryList, List<DistributorAreaVO> distributorAreaList, String router) {

        for (int i = 0; i < distributorAreaList.size(); i++) {
            DistributorAreaVO distributorAreaVO = distributorAreaList.get(i);

            String routerString = router;
            if (StringUtil.isNotEmpty(routerString)) {
                routerString = routerString + distributorAreaVO.getId() + "|";
            } else {
                routerString = "|" + distributorAreaVO.getId() + "|";
            }

            String finalRouterString = routerString;
            int finalI = i;
            updateProductCategoryList.add(new DistributorAreaEntity(){{
                long now = DateUtil.getInt();
                setUpdateTime(now);
                setId(distributorAreaVO.getId());
                setRouter(finalRouterString);
                setParentId(distributorAreaVO.getParentId());
                setSort(finalI);
            }});

            if (Objects.nonNull(distributorAreaVO) && Objects.nonNull(distributorAreaVO.getChildList()) && !distributorAreaVO.getChildList().isEmpty()) {
                getDistributorAreaList(updateProductCategoryList, distributorAreaVO.getChildList(), routerString);
            }
        }
        return updateProductCategoryList;
    }

    private JSONArray getSubDepartmentTree(Map<Long, List<DistributorAreaEntity>> childMap, Long id) {
        List<DistributorAreaEntity> childList = childMap.get(id);
        JSONArray jsonArray = new JSONArray();
        if (childList != null) {
            childList.forEach(item -> {
                JSONObject depJson = new JSONObject();
                depJson.put("value", item.getId());
                depJson.put("label", item.getName());
                depJson.put("type", "department");
                depJson.put("children",getSubDepartmentTree(childMap, item.getId()));
                jsonArray.add(depJson);
            });
        }
        return jsonArray;
    }
}
